﻿#define _CRT_SECURE_NO_WARNINGS 1
#pragma once//防止头文件重复包含
#include <stdio.h>

////变量创建的本质其实是在内存中申请空间
//// 向内存申请4个字节的空间，并把a的值存入
////这四个字节空间中，每个字节都有编号(地址（随机变动的）)
//// a的地址就是&a， a的值就是*(&a)
//// int a = 20;
//
//
//int main()
//{
//	int a = 20;
//	printf("%p\n", &a);//%P是打印地址的格式，
//						//打印出的地址是较小字节的地址
//			           //&a的地址拿出的是较小字节的地址
//
//	int* p= &a;//p是一个指针变量，用来存放地址的，
//			//int* p表示p是一个指向int类型的指针变量
//	*p = 30;//P是指针变量，*p是p指向的地址中的值
//	printf("%d\n", *p);//打印p指向的地址（a）中的值
//
//	return 0;
//}



////指针类型的作用：解引用时，告诉编译器该指针指向的地址中存放的数据类型
////步长：指针类型决定了指针的步长
//int main()
//{
//	int n = 10;
//	int* p = &n;
//	char* p3=(char*) & n;//强制类型转换，把int*类型转换成char*类型
//
//	printf("%d\n", *p);
//	printf("%d\n", *p3);
//
//	printf("%p\n", &n);
//	printf("%p\n", p+1);
//	printf("%p\n", p3+1);
//
//	return 0;
//
//}


//用指针的方式遍历数组
// 第一种方式：
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int sz=sizeof(arr)/sizeof(arr[0]);//计算数组元素个数
//	int* p = arr;//p指向数组首元素
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *p);
//		p++;//指针向后移动
//	}
//
//	return 0;
//}
//
////第二种方式：
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	int i = 0;
//	int* p = &arr[0];//p指向数组首元素
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d", *(p + i));//p+i表示p指向的地址向后移动i*sizeof(int)个字节
//								//指针+ -整数，表示指针向前/后移动i个字节
//	}
//	return 0;
//}



////写一个函数，求字符串的长度
////方法一：利用指针加减整数
//int count_str(char* p)
//{
//	int count = 0; //count计数器
//	while (*p != '\0')
//	{
//		count++;
//		p++;
//	}
//	return count;
//}
//int main()
//{
//	char arr[] = {"abcdef"};
//	int len = count_str(arr);//传的是数组首元素地址
//	printf("%d\n", len);
//	return 0;
//}


////方法二：利用指针减指针
//int count_str(char* p)
//{
//	char* start = p;
//	char* end = p;
//	while (*end != '\0')
//	{
//		end++;
//	} 
//	return end - start;
//}
//int main()
//{
//	char arr[] = { "abcdef" };
//	int len = count_str(arr);//传的是数组首元素地址
//	printf("%d\n", len);
//	return 0;
//}




//
////指针的关系运算
////遍历数组
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int sz = sizeof(arr) / sizeof(arr[0]);//10
//	int* p = arr;//p指向数组首元素,下标为0
//	int i = 0;
//	while (p <=&arr[sz-1])//指针的关系运算
//	{
//		printf("%d ", *p);
//		p++;
//	}
//
//	return 0;
//}



//优化计算字符串个数的函数
//#include<assert.h>
//size_t my_strlen(const char* str)//const修饰指针，防止指针指向的值被修改
//{
//	size_t count = 0;
//	assert(str != NULL);//断言，防止传入空指针
//	while (*str)//*str != '\0','\0'的ASCII码值为0
//	{
//		count++;
//		str++;
//	}
//	return count;
//}
//
//int main()
//{
//	char arr[] = { "abcdef" };
//	size_t len = my_strlen(arr);//返回值是size_t类型（无符号整形）
//    printf("%zd\n", len);
//	return 0;
//}


//
////数组名是一个指向数组首元素的指针，但是它指向的是整个数组，而不是单个元素。
////因此，&arr和arr的值是相同的，都是数组首元素的地址。但是，&arr表示的是整个数组的地址，
//// 而arr表示的是数组首元素的地址。
//int main()
//{
//	int arr[10] = { 0 };
//	int* p = arr;
//	printf("&arr[0]=%p\n", &arr[0]);//等价于p
//	printf("p      =%p\n", p);
//	printf("arr    =%p\n", arr);
//	printf("&arr   =%p\n", &arr);//此处arr代表数组首元素的地址，&arr代表整个数组的地址
//	printf("\n");
//	printf("\n");
//	printf("&arr[0]+1=%p\n", &arr[0] + 1);//等价于p+1
//	printf("arr+1    =%p\n", arr + 1);
//	printf("&arr+1   =%p\n", &arr + 1);//+1代表跳过整个数组，即跳过40个字节
//	return 0;
//	//但有两个例外：
//	//sizeof(arr)返回整个数组的大小，而不是数组首元素的地址。
//	//&arr返回整个数组的地址，而不是数组首元素的地址。
//}




////优化冒泡排序
//void input(int* arr, int sz)
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		scanf("%d", arr + i);//arr+i表示数组首元素地址向后移动i个字节
//	}
//}
//void bubble_sort(int* arr, int sz)
//{
//	
//	int i = 0;//确认排序趟数
//	for (i = 0; i < sz - 1; i++)//sz-1趟排序
//	{
//		int flag = 1;//flag用于优化冒泡排序,如果某一趟排序没有发生交换，则说明数组已经有序，无需再进行排序
//		int j = 0;
//		//每一趟的比较次数
//		for (j = 0; j < sz - 1 - i; j++)//每趟排序都会将一个元素放到正确的位置，所以每趟排序的次数都会减少
//		{
//			count++;
//			if (*(arr + j) > *(arr + j + 1))
//			{
//				flag = 0;//如果发生了交换，则说明数组还未有序，flag置为0
//				int temp = *(arr + j);
//				*(arr + j) = *(arr + j + 1);
//                *(arr + j + 1) = temp;
//			}
//		}
//		if (flag == 1)//如果fla为1，说明数组已经有序，无需再进行排序
//		{
//			 break;
//		}
//	}
//}
//void print_arr(int* arr, int sz)
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *(arr + i));//arr+i表示数组首元素地址向后移动i个字节
//	}
//}
//
//int count = 0;//确认排序次数(全局变量)
//int main()
//{
//	int arr[10] = { 0 };
//	int sz = sizeof(arr) / sizeof(arr[0]);//计算数组元素个数
//	input(arr, sz);//输入数组元素
//	bubble_sort(arr, sz);//冒泡排序
//	print_arr(arr, sz);//打印数组元素
//	printf("\ncount=%d\n", count);//打印排序次数
//	return 0;
//}



//
//二级指针
//int main()
//{
//	int a = 20;
//	int* pa =&a;//pa是一个指针，指向a
//	int* *ppa = &pa;//ppa是一个指针，指向pa
//	printf("%d\n", **ppa);//*ppa表示pa的值，即a的地址，**ppa表示a的值
//	printf("%d\n", *pa);//*pa表示pa的值，即a的地址
//	printf("%p\n", pa);//pa表示pa的值，即a的地址
//	printf("%p\n", &a);//&pa表示ppa的值，即pa的地址
//
//
//	return 0;
// }


//
////指针指向的内存已经释放
//int* test()
//{
//	int a = 10;
//	return &a;
//}
//int main()
//{
//	int* p = test();
//	printf("%d\n", *p);
//	return 0;
//}

//
////数组指针
////用数组指针接收二维数组
//void print(int(*p)[5], int row, int col)
//{
//	int i = 0;
//	for (i = 0; i < row; i++)
//	{
//		int j = 0;
//		for (j = 0; j < col; j++)
//		{
//			printf("%d ", *(*(p + i) + j));//p+i表示数组首元素地址向后移动i个字节，
//											//*(p+i)表示数组首元素地址向后移动i个字节
//		}
//    printf("\n");
//	}
//}
//int man()
//{
//	int a[3][5]={{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};
//	print(a, 3, 5);
//	return 0;
//}


////函数指针
//int Add(int a, int b)
//{
//	return a+b;
//}
//int main()
//{
//	int(*pf)(int, int) = Add;//pf是一个函数指针，指向Add函数
//	int ret2 = pf(5, 20);
//	printf("%d\n", ret2);
//	return 0;
//}

//
////typedef自定义 函数指针类型
//int Add(int a, int b)
//{
//	return a + b;
//}
//typedef int(*pf_t)(int, int);//pf_t是一个函数指针类型，指向的函数有两个int类型的参数，返回值是int类型
//
//int main()
//{
//	pf_t love = Add;//pf_t是一个函数指针，指向Add函数
//    int ret = love(5, 20);
//    printf("%d\n", ret);
//	return 0;
//}


//
////用qsort把整形数据排成升序
//#include <stdlib.h>
//void print_int(int* a, int seed)
//{
//	int i = 0;
//	for (i = 0; i < seed; i++)
//	{
//		printf("%d ", *(a + i));//a+i表示数组首元素地址向后移动i个字节
//	}
//}
//int cmp_int(const void* e1, const void* e2)//void类型的指针可以指向任意类型的数据，不能进行解引用操作
//{
//	return *((int*)e1) - *((int*)e2);//返回值大于0，则e1大于e2，返回值小于0，则e1小于e2
//									//返回值大于0，排序成升序，返回值小于0，排序成降序
//									//const void* e1表示e1是一个指向void类型的指针，void类型的指针可以指向任意类型的数据
//									//*(int*)e1表示将e1强制转换为int*类型，然后解引用，得到e1指向的int类型的数据
//}
//
//int main()
//{
//	int arr[10] = { 3,1,4,7,8,2,0,6,9,5 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	qsort(arr, sz, sizeof(arr[0]), cmp_int);//qsort函数的参数
//	print_int(arr,sz);
//	return 0;
//}
//





//
////使用qsort排结构体成升序
//#include <stdlib.h>
//#include <string.h>
//struct Stu  //结构体
//{
//	char name[20];
//	int age;
//};
//int cmp_stu_by_age(const void* e1, const void* e2)
//{
//	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
//}
//int cmp_stu_by_name(const void* e1, const void* e2)
//{
//	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
//}
//void test2()
//{
//	struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };
//	int sz = sizeof(s) / sizeof(s[0]);
//	qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		printf("%s %d\n", s[i].name, s[i].age);
//	}
//}
//void test1()
//{
//	struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };
//	int sz = sizeof(s) / sizeof(s[0]);
//	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		printf("%s %d\n", s[i].name, s[i].age);
//	}
//	printf("\n");
//}
//int main()
//{
//
//	test1();//测试结构体成员name排成升序
//	test2();//测试结构体成员age排成升序
//	
//	
//	return 0;
//}




//
//
////一般实现计算器的一个加减乘除整数功能（未穷尽）
//int Add(int a, int b)
//{
//	return a + b;
//}
//int Sub(int a, int b)
//{
//	return a - b;
//}
//int Mul(int a, int b)
//{
//	return a * b;
//}
//int Div(int a, int b)
//{
//	return a / b;
//}
//void menu()
//{
//	printf("*************************\n");
//	printf("******** 1.加法程序******\n");
//	printf("******** 2.减法程序******\n");
//	printf("******** 3.乘法程序******\n");
//	printf("******** 4.除法程序******\n");
//	printf("******** 0.退出程序******\n");
//	printf("*************************\n");
//}
//int main()
//{
//	int input = 1;
//	int x = 0, y = 0;
//	int ret = 0;
//	do {
//		menu();
//		printf("请选择：\n");
//		scanf("%d", &input);
//		switch (input)
//		{
//		case 0:
//            printf("退出程序,欢迎下次呼出\n");
//			break;
//		case 1:
//            printf("请输入两个整数：\n");
//            scanf("%lf %lf", &x, &y);
//			ret=Add(x,y);
//			printf("%lf\n", ret);
//			break;
//        case 2:
//			printf("请输入两个整数：\n");
//			scanf("%d %d", &x, &y);
//			ret=Sub(x, y);
//			printf("%d\n", ret);
//			break;
//		case 3:
//			printf("请输入两个整数：\n");
//			scanf("%d %d", &x, &y);
//			ret=Mul(x, y);
//			printf("%d\n", ret);
//            break;
//		case 4:
//			printf("请输入两个整数：\n");
//			scanf("%d %d", &x, &y);
//            ret=Div(x, y);
//			printf("%d\n", ret);
//			break;
//		default:
//			printf("您输入的选项有误,请重新输入\n");
//			break;
//		}
//	} while (input);
//
//	return 0;
//}



//
////函数指针数组优化计算器(转移表)
//int Add(int a, int b)
//{
//	return a + b;
//}
//int Sub(int a, int b)
//{
//	return a - b;
//}
//int Mul(int a, int b)
//{
//	return a * b;
//}
//int Div(int a, int b)
//{
//	return a / b;
//}
//int main()
//{
//	int(*pf[4])(int, int) = { Add,Sub,Mul,Div };
//	int i = 0;
//	for (i = 0; i < 4; i++)
//	{
//		int ret = pf[i](6, 2);//pf[i]表示数组首元素地址向后移动i个字节，
//		//pf[i](5, 20)表示调用数组首元素地址向后移动i个字节指向的函数
//		//分别调用Add,Sub,Mul,Div函数
//		printf("%d\n",ret); 
//	}
//	return 0;
//}




////利用回调函数优化计算器
//int Add(int a, int b)
//{
//	return a + b;
//}
//int Sub(int a, int b)
//{
//	return a - b;
//}
//int Mul(int a, int b)
//{
//	return a * b;
//}
//int Div(int a, int b)
//{
//	return a / b;
//}
//void menu()
//{
//	printf("*************************\n");
//	printf("******** 1.加法程序******\n");
//	printf("******** 2.减法程序******\n");
//	printf("******** 3.乘法程序******\n");
//	printf("******** 4.除法程序******\n");
//	printf("******** 0.退出程序******\n");
//	printf("*************************\n");
//}
//void Cal(int(*pf)(int x, int y))
//{
//	int x = 0, y = 0;
//	int ret = 0;
//	printf("请输入两个整数：\n");
//	scanf("%d %d", &x, &y);
//	ret = pf(x, y);
//	printf("%d\n", ret);
//}
//int main()
//{
//	int input = 0;
//	do {
//		menu();
//		printf("请选择：\n");
//		scanf("%d", &input);
//		
//		switch (input)
//		{
//		case 0:
//			printf("退出计算器\n");
//			break;
//		case 1:
//			Cal(Add);
//			break;
//		case 2:
//			Cal(Sub);
//			break;
//		case 3:
//            Cal(Mul);
//			break;
//		case 4:
//            Cal(Div);
//			break;
//		default:
//            printf("您输入的选项有误,请重新输入\n");
//			break;
//		}
//	} while (input);
//
//
//	return 0;
//}

//
//
////利用转移表实现计算器加减乘除整数功能
//int Add(int a, int b)
//{
//	return a + b;
//}
//int Sub(int a, int b)
//{
//	return a - b;
//}
//int Mul(int a, int b)
//{
//	return a * b;
//}
//int Div(int a, int b)
//{
//	return a / b;
//}
//void menu()
//{
//	printf("*************************\n");
//	printf("******** 1.加法程序******\n");
//	printf("******** 2.减法程序******\n");
//	printf("******** 3.乘法程序******\n");
//	printf("******** 4.除法程序******\n");
//	printf("******** 0.退出程序******\n");
//	printf("*************************\n");
//}
//int main()
//{
//	int input = 0;
//	int x = 0, y = 0;
//	int (*p[5])(int, int) = {0, Add,Sub,Mul,Div };//转移表
//	do {
//		  menu();
//        printf("请选择：\n");
//        scanf("%d", &input);
//		if (input >= 1 && input <= 4)
//		{
//			printf("请输入两个整数：\n");
//			scanf("%d %d", &x, &y);
//		int ret=p[input](x, y);
//		printf("%d\n", ret);
//		}
//		else if (input == 0)
//		{
//		printf("退出程序\n");
//		}
//		else
//		{
//		printf("输入有误，请重新输入\n");
//		}
//		
//
//
//	} while (input);
//
//	return 0;
//}





////初识结构体
//struct Stu
//{
//   char name[20];
//   int age;
//   char gender[3];
//   char phone[15];
//};
//int main()
//{
//	struct Stu s = { "张三", 20, "男", "123456789" };
//	struct Stu p = { "李斯", 18, "男", "112323342" };
//	printf("%s %d %s %s\n", s.name, s.age, s.gender, s.phone);//.表示结构体成员访问
//	printf("%s %d %s %s\n", p.name, p.age, p.gender, p.phone);
//	struct Stu *ps = &s;
//	struct Stu *pr = &p;
//	printf("%s %d %s %s\n", (*ps).name, (*ps).age, (*ps).gender, (*ps).phone);//*ps表示结构体指针指向的结构体
//    printf("%s %d %s %s\n", pr->name, pr->age, pr->gender, pr->phone);//->表示结构体指针指向的结构体成员访问
//	return 0;
//}



//
//
// 
// 
////泛型编程：使⽤回调函数，模拟实现qsort（采⽤冒泡的⽅式）。
//void Print(int* base, size_t sz)
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *(base + i));
//	}
//}
//int  cmp_int(const void* p1, const void* p2)
//{
//	return *((int*)p1) - *((int*)p2);
//}
//void Swap(char* p1, char* p2, size_t width)
//{
//    int i = 0;
//	char tmp = 0;
//	for (i = 0; i < width; i++)
//	{
//		tmp= *p1;
//        *p1 = *p2;
//		*p2 = tmp;
//        p1++;
//		p2++;
//	}
//}
//void bubble_sort(void* base, size_t sz, size_t width, int(*cmp)(const void* p1,const void* p2))
//{
//	//冒泡排序
//	//趟数
//	int i = 0;
//	for (i = 0; i < sz - 1; i++)
//	{
//		//每一趟的两两比较
//		int j = 0;
//		for (j = 0; j < sz - 1 - i; j++)
//		{
//			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
//			{
//				Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
//			}
//		}
//	}
//
//}
//void test1()
//{
//	int arr[] = { 3,1,7,9,8,0,4,6,2,5 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
//	Print(arr,sz);
//}
//int main()
//{
//	test1();
//	return 0;
//}


//
////前提在X86架构下
////数组和指针笔试题：
//int main()
//{
//	int arr[] = { 1,2,3,4 };
//	printf("%zd\n", sizeof(arr));//16
//    //计算的是数组的总大小
//    printf("%zd\n", sizeof(arr + 0));//4
//    //计算的是数组首元素指针的大小
//    printf("%zd\n", sizeof(*arr));//4
//    //计算的是数组首元素的大小  
//    printf("%zd\n", sizeof(arr[1]));//4
//    //计算的是数组第二个元素的大小
//    printf("%zd\n", sizeof(&arr));//4
//    //计算的是数组首元素地址的大小
//    printf("%zd\n", sizeof(*&arr));//16
//    //计算的是数组首元素地址指向的数组的大小
//    printf("%zd\n", sizeof(&arr + 1));//4
//    //计算的是数组首元素地址加1后的地址的大小
//    //跳过整个数组
//    printf("%zd\n", sizeof(&arr[0]));//4
//    //计算的是数组首元素地址的大小
//    printf("%zd\n", sizeof(&arr[0] + 1));//4
//    //计算的是数组首元素地址加1后的地址的大小
//    //第二个元素的地址
//
//
//	return 0;
//}



//
////字符数组和字符串
//#include <string.h>
//int main()
//{
//    char arr[] = { 'a', 'b', 'c', 'd', 'e' ,'f' };
//    printf("%zd\n", sizeof(arr));//整个数组大小为6*1=6
//    printf("%zd\n", sizeof(arr + 0));//指针大小为4
//    printf("%zd\n", sizeof(*arr));//首元素大小为1
//    printf("%zd\n", sizeof(arr[1]));//第二个元素大小为1
//    printf("%zd\n", sizeof(&arr));//数组首元素地址大小为4
//    printf("%zd\n", sizeof(&arr + 1));//数组首元素地址加1后的地址大小为4
//    printf("%zd\n", sizeof(&arr[0] + 1));//数组首元素地址加1后的地址大小为4
//
//
//    printf("%zd\n", strlen(arr));//随机值
//    //strlen计算的是字符串的长度，遇到'\0'停止计算
//    printf("%zd\n", strlen(arr + 0));//随机值
//    //strlen计算的是字符串的长度，遇到'\0'停止计算
//    printf("%zd\n", strlen(*arr));//程序崩溃
//    printf("%zd\n", strlen(arr[1]));//程序崩溃
//    printf("%zd\n", strlen(&arr));//随机值
//    printf("%zd\n", strlen(&arr + 1));//随机值
//    printf("%zd\n", strlen(&arr[0] + 1));//随机值
//
//    return 0;
//}
// 

//
//#include <string.h>
//int main()
//{
//	char arr[] = "abcdef";
//    printf("%zd\n", sizeof(arr));//7
//    printf("%zd\n", sizeof(arr + 0));//4
//    printf("%zd\n", sizeof(*arr));//1
//    printf("%zd\n", sizeof(arr[1]));//1
//    printf("%zd\n", sizeof(&arr));//4
//    printf("%zd\n", sizeof(&arr + 1));//4
//    printf("%zd\n", sizeof(&arr[0] + 1));//4
//
//    printf("\n");
//
//    printf("%zd\n", strlen(arr));//6
//    printf("%zd\n", strlen(arr + 0));//6
//    //printf("%zd\n", strlen(*arr));//程序崩溃
//    //printf("%zd\n", strlen(arr[1]));//程序崩溃
//    printf("%zd\n", strlen(&arr));//6
//    printf("%zd\n", strlen(&arr + 1));//随机值
//    printf("%zd\n", strlen(&arr[0] + 1));//5
//
//
//	return 0;
//}


//
//
//int main()
//{
//	int a[3][4] = { 0 };
//	printf("%zd\n", sizeof(a));//48
//	printf("%zd\n", sizeof(a[0][0]));//4
//	printf("%zd\n", sizeof(a[0]));//16	
//	printf("%zd\n", sizeof(a[0] + 1));//4
//    printf("%zd\n", sizeof(*(a[0] + 1)));//4
//    printf("%zd\n", sizeof(a + 1));//4
//    printf("%zd\n", sizeof(*(a + 1)));//16
//    printf("%zd\n", sizeof(&a[0] + 1));//4
//    printf("%zd\n", sizeof(*(&a[0] + 1)));//16
//    printf("%zd\n", sizeof(*a));//16
//    printf("%zd\n", sizeof(a[3]));//16
//            //a[3]不存在，但是sizeof内部表达式不会真实计算，只是计算类型大小
//	return 0;
//}
//



////多重指针
//int main()
//{
//	char* c[] = { "ENTER","NEW","POINT","FIRST" };
//	char** cp[] = { c + 3,c + 2,c + 1,c };
//	char*** cpp = cp;
//	printf("%s\n", **++cpp);
//	printf("%s\n", *-- * ++cpp + 3);
//	printf("%s\n", *cpp[-2] + 3);
//	printf("%s\n", cpp[-1][-1] + 1);
//	return 0;
//}

//
//
////括号表达式
//int main()
//{
//	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
//	int* p;
//	p = a[0];
//	printf("%d", p[0]);
//	return 0;
//
//}

//
////模拟实现标准库函数strcpy
//#include <assert.h>
//
//char* my_strcpy(char* destination ,const char* sourse)
//{
//	/*assert(destination != NULL);
//	assert(sourse != NULL);*/
//	assert(destination && sourse);
//	char* destination_start = destination;
//	/*while ((* destination++ = * sourse++))//把包括'\0'也拷贝过去，再判断表达式的真就假
//	{
//		;	//++的优先级高于*，先自增再解引用
//	}*/
//	while (*sourse != '\0')
//	{
//		*destination=*sourse;
//		destination++;
//		sourse++;
//	}
//    *destination = *sourse;//把'\0'拷贝过去
//	return destination_start;
//}
//int main()
//{
//	char arr1[] = "abcdef";
//	char arr2[20] = { 0 };
//	char* arr2_str=my_strcpy(arr2, arr1);
//	printf("%s\n", arr2);
//	printf("%s\n",arr2_str);
//	printf("%s\n", my_strcpy(arr2, arr1));
//	return 0;
//}




//
////字符串追加函数strcat ，最好别自己追加自己
//#include <string.h>
//#include <assert.h>
//int main()
//{
//	char arr1[] = "baby";
//	char arr2[20] = {"helloxxxxx"};
//	strcat(arr2, arr1);
//    printf("%s\n", arr2);
//	return 0;
//}


//
////模拟字符串追加函数strcat
//#include <assert.h>
//char* my_strcat(char* destination, const char* sourse)
//{
//	assert(destination && sourse);//防止传入空指针
//	char* ret = destination;//保存目标地址，最后返回
//	while (*destination)//找到目标地址的'\0'
//	{
//		destination++;
//	}
//	while ((*destination++ = *sourse++))//把包括'\0'也拷贝过去，再判断表达式的真就假
//    									//追加赋值
//	{
//		;
//	}
//	
//	return ret;
//}
//int main()
//{
//	char arr1[] = "baby";
//	char arr2[20] = {"hello "};
//	char* ptr=my_strcat(arr2, arr1);
//    printf("%s\n", ptr);
//	return 0;
//}
//

//
////模拟实现strcmp：如果相等返回0，如果目标字符串大返回正数，如果源字符串大返回负数
//int my_strcmp(const char* str1, const char* str2)
//{
//	while (*str1 == *str2)//先比较字符
//	{
//		if (*str1 =='\0')
//		{
//			return 0;
//		}
//		str1++;
//        str2++;
//	}
//	return (*str1 - *str2);
//}
//int main()
//{
//	char arr1[] = "abcdef";
//    char arr2[] = "abq";
//	int ret = my_strcmp(arr1, arr2);
//	printf("%d\n", ret);
//	return 0;
//}


//
////使用strtok函数把字符串分割成单词
//#include <string.h>
//int main()
//{
//	char arr[] = "If I win the game,I will win you.";
//	char copy[50] = { 0 };
//	strcpy(copy, arr);//拷贝一份，防止原字符串被修改
//	printf("%s\n", copy);//副本
//	
//	char* separator = " ,.";//分隔符
//	char* p = NULL;//用来接收strtok的返回值
//
//	for (p = strtok(copy, separator); p != NULL; p = strtok(NULL, separator))
//	{
//		printf("%s\n", p);
//	}
//	printf("%s\n", arr);//原字符串没有被修改
//	return 0;
//}




//
////使用strstr函数查找字符串
//int main()
//{
//	char arr[] = "abcdefghijk";
//	//char* p = "efg";
//	char* p = "opq";
//	char* ret =(char*)strstr(arr, p);//从arr中找p
//	if (ret == NULL)
//	{
//		printf("没有找到%s\n",ret);
//	}
//	else {
//		printf("%s\n", ret);//如果找到了，返回打印输出找到的地址到'\0'结束
//							//如果没找到，返回空指针
//	}
//	
//	return 0;
//}




//
////模拟实现strstr函数
//#include <assert.h>
//const char* my_strstr(const char* str1, const char* str2)
//{
//	assert(str1 && str2);
//	const char* s1 = NULL;
//	const char* s2 = NULL;
//	const char* current = str1;
//
//	if(*str2 == '\0')//如果str2为空字符串，直接返回str1
//		return str1;
//	while (*current != '\0')//从str1中找str2
//	{
//		s1=current;
//        s2=str2;
//		while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
//		{
//			
//			s1++;
//            s2++;
//		}
//		if (*s2 == '\0')//如果找到了，返回当前地址
//			return current;
//        current++;//如果没找到，继续找
//	}
//	
//	return NULL;//如果没找到，返回空指针
//}
//
//
//
//int main()
//{
//	char arr[] = "abbcdefg";
//	char* p = "bbc";
//	const char* ret = my_strstr(arr, p);
//	if (ret == NULL)
//	{
//		printf("没有找到此字符串\n");
//	}
//	else 
//		printf("%s\n", ret);
//	return 0;
//}


//
////循环多次打印strerror函数返回的错误原因
//#include  <string.h>
//int main()
//{
//	int i = 0;
//	for (i = 0; i <= 10; i++)
//	{
//		printf("第%d行的错误原因是：%s\n",i, strerror(i));
//	}
//
//	return 0;
//}



//
////strerror函数使用2：
//#include  <string.h>
//#include <errno.h>
//int main()
//{
//	//打开文件
//
//	FILE* pf = fopen("getmarried.txt","r");
//	if (pf == NULL)
//	{
//		//perror = printf + errno
//		printf("打开文件失败！原因是：%s\n", strerror(errno));
//		perror("打开文件失败！原因是");
//		return 1;
//	}
//	else
//	{
//		printf("打开文件成功！\n");
//		fclose(pf);
//        pf = NULL;
//	}
//	return 0;
//}


//
////memcpy函数使用,将arr1从下标2开始拷贝到arr2中
// #include <string.h>
//int main()
//{
//	int  arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
//	int arr2[20] = { 0 };
//	memcpy(arr2, arr1+2,20);//第二个参数是拷贝的起始位置，第三个参数是拷贝的字节个数
//	for (int i = 0; i < 20; i++)
//	{
//		printf("%d ", arr2[i]);
//	}
//	return 0;
//}


//
////模拟memcpy 函数的使用
//#include <assert.h>
//void* my_memcpy(void* dest, const void* src, size_t num)
//{
//	int i = 0;
//	void* ret = dest;//保存起始地址
//	 assert(dest && src);
//	 for(i=0;i<num;i++)
//	 {
//		 *(char*)dest = *(char*)src;
//		 dest=(char*)dest+1;
//		 src=(char*)src+1;
//	 }
//	 return ret;
//}
//
//
//int main()
//{
//	int  arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
//	int arr2[20] = { 0 };
//	my_memcpy(arr2, arr1 + 2, 20);
//	return 0;
//}



////memmove函数使用
//#include <string.h>
//#include <assert.h>
//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//	memmove(arr + 2, arr, 20);
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", *(arr + i));
//	}
//	return 0;
//}

//
////模拟实现memmove函数
//#include <string.h>
//#include <assert.h>
//void* my_memmove(void* dest, const void* src, size_t num)
//{
//	int i = 0;
//	void* ret = dest;
//	assert(dest && src);
//	if (dest < src)//从前向后拷贝
//	{
//		//for (i = 0; i < num; i++)
//		while(num--)
//		{
//			*((char*)dest) = *((char*)src);
//			 dest = (char*)src+1;
//             src = (char*)src + 1;
//		}
//	}
//	else//从后向前拷贝
//	{
//		while (num--)
//		{
//			*((char*)dest+num)= *((char*)src+num);
//		}
//	}
//	return ret;
//}
//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//	my_memmove(arr + 2, arr, 20);
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", *(arr + i));
//	}
//	return 0;
//}


//
////确定一个系统的大小端字节序存储
//int main()
//{
//	int a = 1;//0x 00 00 00 01
//	if (*((char*)&a) == 1)
//	{
//        printf("小端\n");//小端字节序排序：01 00 00 00
//	}
//	else
//		printf("大端\n");//大端字节序排序：00 00 00 01
//
//	return 0;
//}



////char数据类型存储范围
//int main()
//{
//	char a[1000];//char类型的范围是-128~127
//	int i;
//	for (i = 0; i < 1000; i++)
//	{
//		a[i] = -1 - i;//-1-0=-1，-1-1=-2，-1-2=-3，-1-3=-4，...-1-127=-128
//	}
//	printf("%d", strlen(a));//strlen函数计算的是字符串的长度，遇到'\0'就停止计算
//	return 0;
//}



////char数据类型存储范围
//int main()
//{
//	char a = -1;//-1有符号数，最高位为1，所以a=-1
//	signed char b = -1;//-1有符号数，最高位为1，所以b=-1
//	unsigned char c = -1;//-1无符号数，最高位为0，所以c=255
//	printf("a=%d,b=%d,c=%d", a, b, c);
//	return 0;
//}


//
////浮点型float数据在内存中的存储
//int main()
//{
//	float num = 5.5f;
//	//S=0
//	//M=1.011
//	//E=2		E+127（中间值）=129（可存放的二进制数字）
//	//在内存中的二进制	0 10000001 01100000000000000000000
//	//切割 0100  0000 1011 0000 0000 0000 0000 0000 
//	//转换成十六进制  0x40 B0 00 00
//	return 0;
//}



//#include <math.h>
//int main()
//{
//	float f = 3.45f;
//	if (fabs(f - 3.45f) < 0.00001)//误差范围
//	{//fabs函数用于计算浮点数的绝对值
//        printf("相等\n");
//	}
//	else
//	{
//		printf("不相等\n");
//	}
//	return 0;
//}




////测试const修饰指针
////const放在*号右边，限制的是指针变量本身，指针不能改变指向
////const放在*号左边，限制的是指针指向的值，指针指向的值不能改变
//int main()
//{
//	int m = 10;
//	int n = 20;
//
//	int * const p = &m;//p是常量指针，指向的地址不能改变，指向的值可以改变
//    p = &n;//错误
//    *p = 100;//正确
//
//    //测试const修饰指针指向的值
//    const int* pb = &m;//pc是指针常量，指向的值不能改变，指向的地址可以改变
//    *pb = 100;//错误
//    pb = &n;//正确
//
//	return 0;
//}

////步长影响赋值
//int main()
//{
//	int a = 0x11223344;
//   // int* pa = &a;
//    char* pc = (char*)&a;
//	//*pa = 0;
//	for (int i = 0; i < 4; i++)
//	{
//		*(pc + i) = 0;//pc+i是跳过 i*sizeof(char)个字节
//	}
//	return 0;
//}



////求字符串元素个数
//// 计数器的方式：
//size_t my_strlen(char* dest)
//{
//	size_t count = 0;
//	while (*dest != '\0')
//	{
//		count++;
//		dest++;
//	}
//	return count;
//}
////求字符串元素个数
////指针-指针运算求两个指针之间的元素个数
//size_t my_strlen(char* dest)
//{
//	char* start = dest;
//	char* end = dest;
//	while (*end != '\0')
//	{
//		end++;
//	}
//	return end-start;//指针-指针的绝对值就是两个指针之间的元素个数
//}
//int main()
//{
//	char arr[] = "hello world";
//	size_t ret = my_strlen(arr);
//	printf("%zd\n", ret);
//
//	return 0;
//}




////函数指针数组
//int Add(int x, int y)
//{
//	return x + y;
//}
//int Sub(int x, int y)
//{
//	return x - y;
//}
//int Mul(int x, int y)
//{
//	return x * y;
//}
//int Div(int x, int y)
//{
//	return x / y;
//}
//int main()
//{
//	int(*pf[4])(int, int) = { Add,Sub,Mul,Div };
//	for (int i = 0; i < 4; i++)
//	{
//		int ret = pf[i](1, 2);
//		printf("%d\n", ret);
//	}
//	return 0;
//}


//用函数指针数组写一个整数计算器(转移表)
//int Add(int x, int y)
//{
//	return x + y;
//}
//int Sub(int x, int y)
//{
//	return x - y;
//}
//int Mul(int x, int y)
//{
//	return x * y;
//}
//int Div(int x, int y)
//{
//	return x / y;
//}
//void menu()
//{
//	printf("*************************\n");
//    printf("*******简易计算器********\n");
//    printf("*****1.add     2.sub*****\n");
//    printf("*****3.mul     4.div*****\n");
//    printf("*****    0.exit  ********\n");
//	printf("*************************\n");
//	printf("*************************\n");
//}
//int main()
//{
//	int input = 0;
//	int a = 0, b = 0;
//	int ret = 0;
//	int(*pf[5])(int, int) = { 0,Add,Sub,Mul,Div };
//	do
//	{
//		menu();
//		printf("请选择计算器模式:>\n");
//		scanf("%d", &input);
//		if (input >= 1 && input <= 4)
//		{
//			printf("请输入两个操作数:>\n");
//            scanf("%d%d", &a, &b);
//			ret=pf[input](a, b);
//			printf("结果为:%d\n", ret);
//		}
//		else if (input == 0)
//		{
//			printf("退出计算器\n");
//		}
//		else
//			printf("输入错误，请重新输入\n");
//	} while (input);
//
//	return 0;
//}


////回调函数
//int Add(int x, int y)
//{
//	return x + y;
//}
//int Sub(int x, int y)
//{
//	return x - y;
//}
//int Mul(int x, int y)
//{
//	return x * y;
//}
//int Div(int x, int y)
//{
//	return x / y;
//}
//void Calculate(int(*pf)(int, int))
//{  //形参pf是一个函数指针，指向的函数有int,int两个参数，返回值是int
//	int x = 0, y = 0;
//	printf("请输入两个操作数:>\n");
//	scanf("%d %d", &x, &y);
//	int ret = pf(x, y);
//	printf("结果为:%d\n", ret);
//}
//void menu()
//{
//	printf("*************************\n");
//	printf("*******简易计算器********\n");
//	printf("*****1.add     2.sub*****\n");
//	printf("*****3.mul     4.div*****\n");
//	printf("*****    0.exit  ********\n");
//	printf("*************************\n");
//	printf("*************************\n");
//}
//int main()
//{
//	int input = 0;
//	int a = 0, b = 0;
//	int ret = 0;
//	do
//	{
//		menu();
//		printf("请选择计算器模式:>\n");
//		scanf("%d", &input);
//		switch (input)
//		{
//		case 1:
//			Calculate(Add);//实参是函数名，函数名就是函数的地址
//			break;
//		case 2:
//			Calculate(Sub);
//			break;
//		case 3:
//			Calculate(Mul);
//			break;
//		case 4:
//			Calculate(Div);
//			break;
//		case 0:
//			printf("退出计算器\n");
//			break;
//		default:
//			printf("输入错误，请重新输入\n");
//			break;
//		}
//	} while (input);
//
//	return 0;
//}


////qsort排序
//#include <stdlib.h>
//#include <string.h>
//struct Stu
//{
//	char name[20];
//	int age;
//};
//void love_print(int* arr, int seed)
//{
//	for (int i = 0; i < seed; i++)
//	{
//		printf("%d ", *(arr+i));
//	}
//}
//int cmp_int(const void* x, const void* y)
//{
//	if (*(int*)x > *(int*)y)
//		return 1;
//	else if (*(int*)x < *(int*)y)
//		return -1;
//	else
//		return 0;
//}
//int cmp_str_name(const void* p1, const void* p2)
//{
//	return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
//	//字符串比较函数
//}
//int cmp_str_age(const void* p1, const void* p2)
//{
//	return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
//	//做差法
//}
//void print(struct Stu* arr, int seed)
//{
//	for (int i = 0; i < seed; i++)
//	{
//        printf("%s %d\n", arr->name, arr->age);
//		arr++;
//	}
//}
//void test1()
//{
//	int arr[] = { 2,9,4,6,1,7,3,8,5,0 };
//	int seed = sizeof(arr) / sizeof(arr[0]);
//	printf("排序前:\n");
//	love_print(arr, seed);
//	qsort(arr, seed, sizeof(arr[0]), cmp_int);
//	printf("\n");
//	printf("排序后:\n");
//	love_print(arr, seed);
//}
//void test2()
//{
//	struct Stu arr[] = { {"zhangsan",20},{"lisi",30},{"wangwu",40} };
//	int seed = sizeof(arr) / sizeof(arr[0]);
//	printf("\n");
//	printf("排序前\n");
//	print(arr, seed);
//	qsort(arr, seed, sizeof(arr[0]), cmp_str_name);
//	printf("\n");
//	printf("排序后\n");
//	print(arr,seed);
//}
//void test3()
//{
//	struct Stu arr[] = { {"zhangsan",18},{"lisi",25},{"wangwu",21} };
//	//结构体数组中，每个元素都是结构体类型或者结构体变量，每个结构体变量占用的内存大小是相同的
//	int seed = sizeof(arr) / sizeof(arr[0]);
//	printf("\n");
//	printf("排序前\n");
//	print(arr, seed);
//    qsort(arr, seed, sizeof(arr[0]), cmp_str_age);
//	printf("\n");
//	printf("排序后\n");
//	print(arr, seed);
//}
//int main()
//{
//	//test1();//排序整形数组
//	test2();//排序结构体数组(按名字的字母大小来排序)
//	test3();//排序结构体数组(按年龄大小来排序)
//	return 0;
//}



//#include <stdlib.h>
//
//struct Point {
//    int x;
//    int y;
//};
//int main() {
//    struct Point* ptr = (struct Point*)malloc(sizeof(struct Point));  // 动态分配内存
//    if (ptr == NULL) 
//    {   //if对指针进行判断，如果为空，则说明内存分配失败
//        //是温柔的，不会直接崩溃
//        printf("Memory allocation failed.\n");
//        return 1;
//    }
//    //assert(ptr != NULL); // 断言，暴力解决指针问题，如果为空，则直接崩溃
//    ptr->x = 10;
//    ptr->y = 20;
//    printf("Point: (%d, %d)\n", ptr->x, ptr->y);
//    free(ptr);  // 释放动态分配的内存
//    return 0;
//}



//#include <stdlib.h>
//struct Point {
//    int x;
//    int y;
//};
//// 函数接收一个结构体指针，并修改其成员
//void modifyPoint(struct Point* ptr) {
//    ptr->x = 100;
//    ptr->y = 200;
//}
//int main() {
//    struct Point* p = (struct Point*)malloc(sizeof(struct Point));
//    if (p == NULL) {
//        printf("Memory allocation failed.\n");
//        return 1;
//    }
//    modifyPoint(p);  //传址调用函数修改结构体成员
//    printf("Point: (%d, %d)\n", p->x, p->y);
//    free(p);
//    return 0;
//}




////用自定义的bubble_maker函数来模拟qsort排序
//#include <string.h>
//struct Stu
//{
//	char name[20];
//	int age;
//};
//void love_print(int* arr, int seed)
//{
//	for (int i = 0; i < seed; i++)
//	{
//		printf("%d ", *(arr + i));
//	}
//}
//void print(struct Stu* arr, int seed)
//{
//	for (int i = 0; i < seed; i++)
//	{
//		printf("%s %d\n", arr->name, arr->age);
//		arr++;
//	}
//}
//void Swap(char* buff1,char* buff2,size_t size)
//{
//	//以每个字节为单位进行交换
//	char tmp = 0;
//	for (int i = 0; i < size; i++)
//	{
//		tmp = *buff1;
//        *buff1 = *buff2;
//        *buff2 = tmp;
//		buff1++;
//		buff2++;
//	}
//}
////用冒泡排序模拟qsort排序
//void bubble_maker(void* base, int seed, int size, int(*cmp)(const void* p1, const void* p2))
//{
//	//cmp指针指向你想排序什么样的数据类型的函数
//	for (int i = 0; i < seed - 1; i++)
//	{
//		//趟数
//		for (int j = 0; j < seed - 1 - i; j++)
//		{
//			//元素对数
//			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)//调用所排序的函数
//			{
//				//交换函数
//				Swap((char*)base + j * size, (char*)base + (j + 1) * size,size);
//			}
//		}
//	}
//}
//int cmp_int(const void* p1, const void* p2)//想排序整形数据的函数
//{
//	return *((int*)p1) - *((int*)p2);
//}
//int cmp_struct(const void* p1, const void* p2)
//{
//	//想排序结构体名字数据的函数
//	return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
//}
//void test1()
//{
//	int arr[] = { 2,9,4,6,1,7,3,8,5,0 };
//	int seed = sizeof(arr) / sizeof(arr[0]);
//	printf("排序前:\n");
//	love_print(arr, seed);
//	bubble_maker(arr, seed, sizeof(arr[0]), cmp_int);
//	printf("\n");
//	printf("排序后:\n");
//	love_print(arr, seed);
//}
//void test2()
//{
//	struct Stu arr[] = { {"zhangsan",20},{"lisi",30},{"wangwu",40} };
//	int seed = sizeof(arr) / sizeof(arr[0]);
//	printf("\n");
//	printf("排序前\n");
//	print(arr, seed);
//	bubble_maker(arr, seed, sizeof(arr[0]), cmp_struct);
//	printf("\n");
//	printf("排序后\n");
//	print(arr, seed);
//}
//
//
//int main()
//{
//	test1();//交换整形数据
//	test2();//交换结构体数据
//	return 0;
//}


////测试结构体大小
//#include <stddef.h>
//struct S1 {
//	char c1;
//	char c2;
//	int n;
//};
//struct S2 {
//	char c1;
//	int n;
//	char c2;
//}s2;
//int main()
//{
//	struct S1 s1 = { 0 };
//	//offsetof宏，计算结构体成员相对于结构体首地址的偏移量
//	printf("%zd\n",offsetof(struct S1, c1));
//	printf("%zd\n", offsetof(struct S1, c2));
//	printf("%zd\n", offsetof(struct S1, n));
//	printf("%d\n", sizeof(s1));//8
//	printf("%d\n", sizeof(s2));//12
//	printf("%zd\n", offsetof(struct S2, c1));
//	printf("%zd\n", offsetof(struct S2, n));
//	printf("%zd\n", offsetof(struct S2, c2));
//	return 0;
//}


////计算嵌套结构体的大小
//#include <stddef.h>
//typedef struct S1 {
//	char a1;
//	char a2;
//	double a3;
//}s1;
//typedef struct S2 {
//	char b1;
//	s1 s3;
//	int b2;
//}s2;
//int main()
//{
//	printf("%d\n", sizeof(s1));
//	printf("%zd\n", offsetof(s1, a1));
//	printf("%zd\n", offsetof(s1, a2));
//	printf("%zd\n", offsetof(s1, a3));
//	printf("%d\n", sizeof(s2));
//	printf("%zd\n", offsetof(s2, b1));
//	printf("%zd\n", offsetof(s2, s3));
//	printf("%zd\n", offsetof(s2, b2));
//	return 0;
//}


////结构体传值调用
//struct S1 {
//	int arr[20];
//	char c;
//	int b;
//}s1 = { {1,2,3,4,10},'a',100 };
//void print(struct S1 s1,int seed)
//{
//	for (int i = 0; i < seed; i++)
//	{
//		printf("%d ", s1.arr[i]);
//	}
//	printf("\n");
//	printf("%c\n", s1.c);
//	printf("%d\n", s1.b);
//}
//
//int main()
//{ 
//	int seed = sizeof(s1.arr) / sizeof(s1.arr[0]);//成员数组的元素个数
//	int times = 5;//截停个数（未初始化完全的数组成员）
//	print(s1,times);
//	return 0;
//}


////结构体指针传值调用
//struct S1 {
//	int arr[15];
//	int agel;
//	char c1;
//}s1;
//void print(struct S1* ps1)
//{
//	for (int i = 0; i < 5; i++)
//	{
//        printf("%d ", ps1->arr[i]);
//	}
//	printf("\n");
//	printf("%c\n", ps1->c1);
//    printf("%d\n", ps1->agel);
//}
//int main()
//{
//	struct S1 s1 = { {1,2,3,4,5 }, 20, 'a'};
//	print(&s1);
//	return 0;
//}


//位段
//struct S1 {
//	int _a : 2;
//	int _b : 5;
//	int _c : 10;
//	int _d : 30;//不能超出变量类型所占的位数
//	//int _e : 33;//超出变量类型所占的位数，报错
//int main()
//{
//	struct S1 s1 = { 0 };
//	printf("%d\n", sizeof(struct S1));
//}



////位段的使用和内存分配
//struct D1{
//	char a : 3;
//	char b : 4;
//	char c : 5;
//	char d : 4;
//}d1;
//int main()
//{
//	struct D1 d1 = { 0 };
//	d1.a = 10;
//	d1.b = 12;
//	d1.c = 3;
//	d1.d = 4;
//	printf("%d\n", sizeof(struct D1));
//	return 0;
//}



#if 0
//结构体数组——两种访问方式
typedef struct Student {
	char name[10];
	float scores;
	int age;
}Student;

int main()
{
	Student stu[3] = {
		{"张三", 90.5f, 18},
		{"李四",80.5f},
		{"王五", 70.5f, 20}
	};//结构体数组初始化
	
	//获取首元素信息（点访问）
    printf("%s\n", stu[0].name);//理解成数组下标
    printf("%f\n", stu[0].scores);
    printf("%d\n", stu[0].age);

	//获取第二个元素信息（箭头访问）
    printf("%s\n", stu->name);
    printf("%f\n", stu->scores);
    printf("%d\n", stu->age);
	return 0;
}
#endif


// 动态分配结构体大小的内存
#if 0
#include <stdlib.h> 

struct Student* createStudent() {
  
    struct Student* p = (struct Student*)malloc(sizeof(struct Student));
    if (p != NULL) {  // 分配成功
        strcpy(p->name, "David");
        p->age = 21;
    }
    return p;
}

// 使用后需释放内存
void freeStudent(struct Student* p) {
    free(p);  // 释放动态分配的内存
    p = NULL; // 避免野指针
}

//定义学生结构
struct Student
{
    char name[20];
    int age;
};
int main()
{
    struct Student* p = createStudent();
    printf("Name: %s, Age: %d\n", p->name, p->age);
    freeStudent(p);

	return 0;
}
#endif


//单链表结构
#if 0
typedef struct Node {
    int data;//数据域
    struct Node* next;//指针域
}Node;

int main()
{
    //创建头结点
    Node node1 = { 0 }, node2 = { 0 };
    node1.data = 1;
    node1.next = &node2;
    node2.data = 2;
    node2.next = NULL;
    Node* head = &node1;
    while (head != NULL) {
        printf("%d->", head->data);
        head = head->next;
    }
    printf("NULL\n");
    return 0;
}
#endif



//嵌套结构体
#if 1
// 内部结构体：日期
struct Date {
    int year;
    int month;
    int day;
};

// 外部结构体：学生
struct Student {
    char name[20];
    int age;
    struct Date birthday;  // 嵌套日期结构体
};

int main() {
    // 初始化嵌套结构体
    struct Student s = {
        "Alice",
        20,
        {2004, 8, 01}  // 初始化内部结构体
    };

    // 访问嵌套成员
    printf("姓名：%s\n", s.name);
    printf("年龄：%d\n", s.age);
    printf("生日：%d年%d月%d日\n",
        s.birthday.year,  // 访问内部结构体的year成员
        s.birthday.month,
        s.birthday.day);

    // 修改嵌套成员
    s.birthday.year = 2005;
    printf("修改后生日：%d年%d月%d日\n",
        s.birthday.year,
        s.birthday.month,
        s.birthday.day);

    return 0;
}
#endif